package com.secsbrain.development.web.controller;

import java.net.URLDecoder;
import java.util.Date;

import com.alibaba.fastjson.JSON;
import com.secsbrain.development.biz.IDeployPlanService;
import com.secsbrain.development.biz.IDeployPlanTestService;
import com.secsbrain.development.biz.IProjectAppService;
import com.secsbrain.development.biz.constant.EnumDefinition;
import com.secsbrain.development.dal.model.DeployPlan;
import com.secsbrain.development.dal.model.DeployPlanTest;
import com.secsbrain.frame.lock.Callback;
import com.secsbrain.frame.lock.DistributedLockTemplate;
import io.swagger.annotations.Api;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.util.Assert;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;

import com.secsbrain.common.ResponseVo;
import com.secsbrain.development.client.iface.PlanService;
import com.secsbrain.development.client.model.Plan;
import com.secsbrain.development.client.model.TestResult;
import springfox.documentation.annotations.ApiIgnore;

/**
 * 发布计划控制层
 * @author zhaoyi
 *
 */
@RestController
@EnableEurekaClient
@ApiIgnore
public class PlanServiceImpl implements PlanService{
	
    private static final Logger logger = LoggerFactory.getLogger(PlanServiceImpl.class);

    @Autowired
    IDeployPlanService deployPlanService;
    
    @Autowired
    IDeployPlanTestService deployPlanTestService;
    
    @Autowired
	DistributedLockTemplate distributedLockTemplate;
    
    @Autowired
    IProjectAppService projectAppService;
    
	/* (non-Javadoc)
	 * @see PlanService#createPlan()
	 */
	@Override
	public ResponseVo<?> createPlan(@RequestBody Plan plan) {
		logger.debug("创建发布计划开始...参数：{}", JSON.toJSONString(plan));
		
		Assert.hasText(plan.getBuildDes(), "buildDes不能为空");
		Assert.hasText(plan.getBuildId(), "buildId不能为空");
		Assert.hasText(plan.getBuildName(), "buildName不能为空");
		Assert.hasText(plan.getProjectDes(), "projectDes不能为空");
		Assert.hasText(plan.getProjectId(), "projectId不能为空");
		Assert.hasText(plan.getProjectName(), "projectName不能为空");
		
		DeployPlan deployPlanParam=new DeployPlan();
		deployPlanParam.setBuildId(plan.getBuildId());
		
		this.decode(deployPlanParam,plan);
		
		int count=deployPlanService.selectCount(deployPlanParam);
		Assert.isTrue(count<=0, "buildId:"+plan.getBuildId()+"已经存在");

		DeployPlan deployPlan=new DeployPlan();
		BeanUtils.copyProperties(plan, deployPlan);
		deployPlan.setCreateTime(new Date());
		deployPlan.setCreateName(StringUtils.isEmpty(plan.getCreateName())?"禅道":plan.getCreateName());
		deployPlanService.insertSelective(deployPlan);
		return ResponseVo.getSuccessResponse();
	}
	
	private void decode(DeployPlan deployPlanToDB,Plan deployPlanParam){
		try {
			if(StringUtils.isNotEmpty(deployPlanParam.getBuildName())){
				deployPlanParam.setBuildName(URLDecoder.decode(deployPlanParam.getBuildName(), "UTF-8"));
			}
			if(StringUtils.isNotEmpty(deployPlanParam.getBuildDes())){
				deployPlanParam.setBuildDes(URLDecoder.decode(deployPlanParam.getBuildDes(), "UTF-8"));
			}
			if(StringUtils.isNotEmpty(deployPlanParam.getProjectName())){
				deployPlanParam.setProjectName(URLDecoder.decode(deployPlanParam.getProjectName(), "UTF-8"));
			}
			if(StringUtils.isNotEmpty(deployPlanParam.getProjectDes())){
				deployPlanParam.setProjectDes(URLDecoder.decode(deployPlanParam.getProjectDes(), "UTF-8"));
			}
		} catch (Exception e) {
			logger.error("",e);
		}
	}
	
	/* (non-Javadoc)
	 * @see PlanService#updatePlan(Plan)
	 */
	@Override
	public ResponseVo<?> updatePlan(@RequestBody Plan plan) {
		Assert.hasText(plan.getBuildId(), "buildId不能为空");
		
		DeployPlan deployPlan=new DeployPlan();
		deployPlan.setBuildDes(plan.getBuildDes());
		deployPlan.setBuildName(plan.getBuildName());
		deployPlan.setProjectName(plan.getProjectName());
		deployPlan.setProjectDes(plan.getProjectDes());
		deployPlan.setUpdateName(StringUtils.isEmpty(plan.getCreateName())?"禅道":plan.getCreateName());
		deployPlan.setUpdateTime(new Date());
		
		this.decode(deployPlan,plan);
		
		DeployPlan whereEntity=new DeployPlan();
		whereEntity.setBuildId(plan.getBuildId());
		boolean flag=deployPlanService.updateSelective(deployPlan, whereEntity);
		Assert.isTrue(flag, "更新发布计划失败");
		return ResponseVo.getSuccessResponse();
	}

	/* (non-Javadoc)
	 * @see PlanService#delPlan(java.lang.Long)
	 */
	@Override
	public ResponseVo<?> delPlan(@PathVariable("buildId") String buildId) {
		Assert.hasText(buildId, "buildId不能为空");
		
		DeployPlan deployPlanDel=new DeployPlan();
		deployPlanDel.setBuildId(buildId);
		boolean flag=deployPlanService.deleteSelective(deployPlanDel);
		Assert.isTrue(flag, "删除发布计划失败");
		return ResponseVo.getSuccessResponse();
	}

	/* (non-Javadoc)
	 * @see PlanService#testCallback(TestResult)
	 */
	@Override
	public ResponseVo<?> testCallback(@RequestBody TestResult testResult) {
		logger.debug("测试结果回调开始...参数：{}",JSON.toJSONString(testResult));
		
		//防止立即回调的情况
		try {
			Thread.sleep(2000);
		} catch (InterruptedException e) {
		}
		
		Assert.hasText(testResult.getBuildId(), "buildId不能为空");
		Assert.notNull(testResult.getCode(), "code不能为空");
		Assert.notNull(testResult.getDetailList(), "detailList不能为空");
		
		DeployPlan deployPlanParam=new DeployPlan();
		deployPlanParam.setBuildId(testResult.getBuildId());
		DeployPlan deployPlan=deployPlanService.selectOne(deployPlanParam);
		Assert.notNull(deployPlan, "不存在buildId为"+testResult.getBuildId()+"的发布计划");

		DeployPlanTest deployPlanTestParam=new DeployPlanTest();
		deployPlanTestParam.setPlanId(deployPlan.getId());
		DeployPlanTest deployPlanTest=deployPlanTestService.selectOne(deployPlanTestParam);
		Assert.notNull(deployPlanTest, "不存在buildId为"+testResult.getBuildId()+"的自动化测试申请记录");

		//TODO 不允许重复回调
		Date nowDate=new Date();

		DeployPlanTest deployPlanTestUp=new DeployPlanTest();
		deployPlanTestUp.setId(deployPlanTest.getId());
		deployPlanTestUp.setStatus(EnumDefinition.TestStatus.FINISH.getCode());
		deployPlanTestUp.setDetail(JSON.toJSONString(testResult.getDetailList()));
		deployPlanTestUp.setTestCode(testResult.getCode());
		deployPlanTestUp.setUpdateTime(nowDate);
		
		distributedLockTemplate.execute("update_deployPlanTest_"+deployPlanTest.getId(), 5000, new Callback() {

			@Override
			public Object onGetLock() throws InterruptedException {
				deployPlanTestService.updateSelectiveById(deployPlanTestUp);
				return null;
			}

			@Override
			public Object onTimeout() throws InterruptedException {
				return null;
			}
			
		});
		return ResponseVo.getSuccessResponse();
	}

}
